In [1]:
# This is hello_who.py
def hello(who):
print("Hello {}!".format(who))
if __name__ == "__main__":
hello("mamma")
In [2]:
# This is hello_who.py # <-- i commenti iniziano con `#`
# possono essere all'inizio o a fine riga
def hello(who): # <-- la funzione di definisce con `def`
print("Hello {}!".format(who)) # <-- la stampa con `print` e le stringhe con `format`
if __name__ == "__main__": # <-- [verifica di esecuzione e non di import](https://docs.python.org/2/library/__main__.html)
hello("mamma") # <-- invoco la funzione con il valore
Le classiche sono:
<TAB>
: settate il vostro editor!Le convenzioni per le docstring
sono descritte nel PEP 257
in particolare:
Mie convenzioni:
In [43]:
# creazione
l = [1,2,3,10,"a", -12.333, 1024, 768, "pippo"]
# concatenazione
l += ["la", "concatenazione", "della", "lista"]
# aggiunta elementi in fondo
l.append(32)
l.append(3)
print(u"la lista è {}".format(l))
l.remove(3) # rimuove la prima occorrenza
print(u"la lista è {}".format(l))
i = l.index(10) # restituisce l'indice della prima occorrenza del valore 10
print(u"l'indice di 10 è {}".format(i))
print(u"il valore all'indice 3 è {}".format(l[3]))
print(u"** vediamo come funziona lo SLICING delle liste")
print(u"Ecco i primi 3 valori della lista {}".format(l[:3]))
print(u"e poi i valori dal 3o al penultimo {}".format(l[3:-1]))
print(u"e poi i valori dal 3o al penultimo, ma ogni 2 {}".format(l[3:-1:2]))
print("\n***FUNZIONI RANGE e XRANGE***\n")
l2 = range(1000) # questi sono i primi 1000 valori da 0 a 999
print(u"ecco la lista ogni 50 elementi di n <=1000: {}".format(l2[::50]))
# LA FUNZIONE xrange è comoda per ottenere un oggetto tipo (ma non = a ) un generatore
# da cui i numeri vengono appunto generati al momento dell'accesso all'elemento stesso
# della sequenza
# Il codice di prima dà errore
try:
l2 = xrange(1000) # questi sono i primi 1000 valori da 0 a 999 ma senza occupare RAM
print(u"ecco la lista ogni 50 elementi di n <= 1000: {}".format(l2[::50]))
except Exception as e:
print("ECCEZIONE {}: {}".format(type(e), e))
# Il codice che funziona con lo slice valuta xrange in una lista quindi
# risulta inutile
l2 = list(xrange(1000)) # questi sono i primi 1000 valori da 0 a 999 ma senza occupare RAM
print(u"ecco la lista ogni 50 elementi di n <= 1000: {}\n".format(l2[::50]))
## ma si può fare direttamente con range o xrange!
print(u"[OK] lista ogni 50 elementi <= 1000: {}".format(range(0,1000,50)))
In [44]:
print("***PER FARE UN CICLO FOR CON INDICE INCREMENTALE SI USA XRANGE!")
for el in xrange(1,21):
print("numero {}".format(el))
print("***PER NUMERARE GLI ELEMENTI DI UNA LISTA SI USA ENUMERATE!")
for i, el in enumerate(l, start=10): # numero partendo da 10, se start non specificato parto da 0
print("Il contenuto {} si trova all'indice {}".format(el, i))
In [45]:
# definizione
d = {"nome": "Luca", "cognome": "Ferroni", "classe": 1980}
# aggiornamento
d.update({
"professioni" : ["docente", "lavoratore autonomo"]
})
# recupero valore per chiave certa (__getitem__)
print(u"Il nome del personaggio è {}".format(d["nome"]))
# sfrutto il mini-formato di template per le stringhe
# https://docs.python.org/2.7/library/string.html#formatspec
print(u"Il personaggio è {nome} {cognome} nato nel {classe}".format(**d))
# Recupero di un valore per una chiave opzionale
print(u"'nome' è una chiave che esiste con valore = {}, 'codiceiban' invece non esiste = {}".format(
d.get('nome'), d.get('codiceiban')))
print(u"Se avessi usato la __getitem__ avrei avuto un KeyError")
# rimozione di una chiave dal dizionario
print(u"Rimuovo il nome dal dizionario con d.pop('nome')")
d.pop('nome')
print(u"'nome' ora non esiste con valore = {}, come 'codiceiban' = {}".format(
d.get('nome'), d.get('codiceiban')))
print(u"Allora, se non trovi la chiave 'nome' allora dimmi 'Pippo'. Cosa dici?")
print(d.get('nome', 'Pippo'))
In [52]:
print("\n***PER ITERARE SU TUTTI GLI ELEMENTI DI UN DIZIONARIO SI USA .iteritems()***\n")
for key, value in d.iteritems():
print("Alla chiave {} corrisponde il valore {}".format(key,value))
print("\n***DIZIONARI E ORDINAMENTO***\n")
data_input = [('a', 1), ('b', 2), ('l', 10), ('c', 3)]
d1 = dict(data_input)
import collections
d2_ord = collections.OrderedDict(data_input)
print("input = {}".format(data_input))
print("dizionario non ordinato = {}".format(d1))
print("dizionario ordinato = {}".format(d2_ord))
print("lista di coppie da diz NON ordinato = {}".format(d1.items()))
print("lista di coppie da diz ordinato = {}".format(d2_ord.items()))
Ogni oggetto ha:
Tipi di dato immutable sono:
Tipi di dato mutable sono:
Da http://stackoverflow.com/questions/11328920/is-python-strongly-typed/11328980#11328980 (v. anche i commenti)
Python is strongly, dynamically typed.
As for example
bob = 1
bob = "bob"
This works because the variable does not have a type; it can name any object. After bob=1, you'll find that type(bob) returns int, but after bob="bob", it returns str. (Note that type is a regular function, so it evaluates its argument, then returns the type of the value.)
Nessuno dei due! V. https://jeffknupp.com/blog/2012/11/13/is-python-callbyvalue-or-callbyreference-neither/
Call by object, or call by object reference.
Concetto base: in python una variabile è solo un nome per un oggetto (= la tripla id,tipo,valore)
In sostanza il comportamento dipende dal fatto che gli oggetti nominati dalle variabili sono mutable o immutable.
Seguono esempi:
In [8]:
def foo(bar):
bar.append(42)
print(bar)
# >> [42]
answer_list = []
foo(answer_list)
print(answer_list)
# >> [42]
In [9]:
def foo(bar):
bar = 'new value'
print (bar)
# >> 'new value'
answer_list = 'old value'
foo(answer_list)
print(answer_list)
# >> 'old value'
Una funzione si definisce con def <nomefunzione>([parametri])
dove i parametri possono essere:
def hello(who)
def hello(who='')
o who=None o who='default'def hello(who, say="How are you?")
arbitrari sia posizionali con il simbolo *
o nominali con **
. Come convenzione si utilizzano i nomi args
e kw
o kwargs
. Ad es: def hello(who, say="How are you?", *args, **kw)
I simboli *
e **
indicano rispettivamente la rappresentazione di una lista come una sequenza di elementi, e di un dizionario come una sequenza di parametri <chiave>=<valore>
http://www.saltycrane.com/blog/2008/01/python-variable-scope-notes/
e ricordatevi che:
for i in [1,2,3]: print(i) print("Sono fuori dal ciclo e posso vedere che i={}".format(i))
I namespace in python sono raccoglitori di nomi e posson essere impliciti o espliciti. Sono impliciti lo spazio dei nomi __builtin__
e __main__
. Sono espliciti, le classi, gli oggetti, le funzioni e in particolare i moduli.
Posso importare un modulo che mi va a costituire un namespace con import <nomemodulo>
e accedere a tutti i simboli top-level inseriti nel modulo come <nomemodulo>.<simbolo>
.
L'importazione di simboli singoli all'interno di un modulo in un altro namespace si può fare con from <nomemodulo> import <simbolo>
. Quello che non si dovrebbe fare è importare tutti i simboli di un modulo dentro un altro nella forma: from <nomemodulo> import *
. Non fatelo, a meno che non strettamente necessario.
Lo stack delle eccezioni builtin, ossia già comprese nel linguaggio python sono al link: https://docs.python.org/2/library/exceptions.html#exception-hierarchy
Derivando da essere facilmente se ne possono definire di proprie.
La gestione delle eccezioni avviene in blocchi:
try:
...
except [eccezione] [as variabile]:
...
else:
...
finally:
...
Pratica del Duck Typing!
« If it looks like a duck, swims like a duck, and quacks like a duck, then it probably is a duck. »
Segue esempio di composizione del saluto con la gestione delle eccezioni:
In [2]:
# -*- coding: utf-8 -*-
# This is hello_who_3.py
import sys # <-- importo un modulo
def compose_hello(who, force=False): # <-- valore di default
"""
Get the hello message.
"""
try: # <-- gestione eccezioni `Duck Typing`
message = "Hello " + who + "!"
except TypeError: # <-- eccezione specifica
# except TypeError as e: # <-- eccezione specifica su parametro e
print("[WARNING] Il parametro `who` dovrebbe essere una stringa")
if force: # <-- controllo "if"
message = "Hello {}!".format(who)
else:
raise # <-- solleva eccezione originale
except Exception:
print("Verificatasi eccezione non prevista")
else:
print("nessuna eccezione")
finally:
print("Bye")
return message
def hello(who='world'): # <-- valore di default
print(compose_hello(who))
if __name__ == "__main__":
hello("mamma")
In [3]:
hello("pippo")
In [4]:
hello(1)
In [25]:
ret = compose_hello(1, force=True)
print("Ha composto {}".format(ret))
In [29]:
try:
hello(1)
except TypeError as e:
print("{}: {}".format(type(e).__name__, e))
print("Riprova")
In [ ]:
fib(0) --> 0
fib(1) --> 1
fib(2) --> 1
fib(3) --> 2
fib(n) --> fib(n-1) + fib(n-2)
In [ ]:
import pytest
from myprogram import fib
def test_fib_ok_small():
assert fib(0) == 0
assert fib(1) == 1
assert fib(2) == 1
assert fib(3) == 2
def test_fib_raise_if_string():
with pytest.raises(TypeError):
fib("a")
def test_fib_raises_lt_zero():
with pytest.raises(ValueError):
fib(-1)